/**********************************************************************
  Copyright(c) 2024 Intel Corporation All rights reserved.

  Redistribution and use in source and binary forms, with or without
  modification, are permitted provided that the following conditions
  are met:
    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in
      the documentation and/or other materials provided with the
      distribution.
    * Neither the name of Intel Corporation nor the names of its
      contributors may be used to endorse or promote products derived
      from this software without specific prior written permission.

  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
**********************************************************************/

/*
 * AES self tests
 */

#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h>

#include "aes_cbc.h"
#include "aes_cbc_internal.h"
#include "aes_xts_internal.h"
#include "aes_gcm.h"
#include "aes_gcm_internal.h"
#include "aes_keyexp_internal.h"

#include "internal_fips.h"
#include "types.h"
#include "test.h"

struct self_test_cbc_vector {
        const uint8_t *cipher_key; /* Cipher key */
        size_t cipher_key_size;    /* Key size in bytes */
        uint8_t *cipher_iv;        /* Initialization vector */
        const uint8_t *plaintext;  /* Plaintext */
        size_t plaintext_size;     /* Plaintext length in bytes */
        const uint8_t *ciphertext; /* Ciphertext */
        const char *description;   /* Description of vector */
};

struct self_test_xts_vector {
        uint8_t *cipher_key1;      /* Cipher key 1 */
        uint8_t *cipher_key2;      /* Cipher key 2 */
        size_t cipher_key_size;    /* Key size in bytes */
        uint8_t *tweak;            /* 16-byte tweak */
        const uint8_t *plaintext;  /* Plaintext */
        size_t plaintext_size;     /* Plaintext length in bytes */
        const uint8_t *ciphertext; /* Ciphertext */
        const char *description;   /* Description of vector */
};

struct self_test_gcm_vector {
        const uint8_t *key;        /* Cipher key */
        size_t cipher_key_size;    /* Key size in bytes */
        uint8_t *cipher_iv;        /* Initialization vector */
        const uint8_t *plaintext;  /* Plaintext */
        size_t plaintext_size;     /* Plaintext length in bytes */
        const uint8_t *ciphertext; /* Ciphertext */
        const uint8_t *aad;        /* AAD */
        size_t aad_size;           /* AAD size */
        uint8_t *tag;              /* Authenticationg tag */
        size_t tag_size;           /* Authenticationg tag size */
        const char *description;   /* Description of vector */
};

/*
 *  AES-CBC Test vectors from
 *  http://csrc.nist.gov/publications/fips/fips197/fips-197.pdf
 */

static const uint8_t aes_cbc_128_key[] = { 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6,
                                           0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c };

static uint8_t aes_cbc_128_iv[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
                                    0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f };

static const uint8_t aes_cbc_128_plaintext[] = {
        0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, 0xe9, 0x3d, 0x7e, 0x11, 0x73,
        0x93, 0x17, 0x2a, 0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c, 0x9e, 0xb7,
        0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51, 0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4,
        0x11, 0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef, 0xf6, 0x9f, 0x24, 0x45,
        0xdf, 0x4f, 0x9b, 0x17, 0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10
};

static const uint8_t aes_cbc_128_ciphertext[] = {
        0x76, 0x49, 0xab, 0xac, 0x81, 0x19, 0xb2, 0x46, 0xce, 0xe9, 0x8e, 0x9b, 0x12,
        0xe9, 0x19, 0x7d, 0x50, 0x86, 0xcb, 0x9b, 0x50, 0x72, 0x19, 0xee, 0x95, 0xdb,
        0x11, 0x3a, 0x91, 0x76, 0x78, 0xb2, 0x73, 0xbe, 0xd6, 0xb8, 0xe3, 0xc1, 0x74,
        0x3b, 0x71, 0x16, 0xe6, 0x9e, 0x22, 0x22, 0x95, 0x16, 0x3f, 0xf1, 0xca, 0xa1,
        0x68, 0x1f, 0xac, 0x09, 0x12, 0x0e, 0xca, 0x30, 0x75, 0x86, 0xe1, 0xa7
};

static const uint8_t aes_cbc_192_key[] = { 0x8e, 0x73, 0xb0, 0xf7, 0xda, 0x0e, 0x64, 0x52,
                                           0xc8, 0x10, 0xf3, 0x2b, 0x80, 0x90, 0x79, 0xe5,
                                           0x62, 0xf8, 0xea, 0xd2, 0x52, 0x2c, 0x6b, 0x7b };

static uint8_t aes_cbc_192_iv[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
                                    0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f };

static const uint8_t aes_cbc_192_plaintext[] = {
        0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, 0xe9, 0x3d, 0x7e, 0x11, 0x73,
        0x93, 0x17, 0x2a, 0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c, 0x9e, 0xb7,
        0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51, 0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4,
        0x11, 0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef, 0xf6, 0x9f, 0x24, 0x45,
        0xdf, 0x4f, 0x9b, 0x17, 0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10
};

static const uint8_t aes_cbc_192_ciphertext[] = {
        0x4f, 0x02, 0x1d, 0xb2, 0x43, 0xbc, 0x63, 0x3d, 0x71, 0x78, 0x18, 0x3a, 0x9f,
        0xa0, 0x71, 0xe8, 0xb4, 0xd9, 0xad, 0xa9, 0xad, 0x7d, 0xed, 0xf4, 0xe5, 0xe7,
        0x38, 0x76, 0x3f, 0x69, 0x14, 0x5a, 0x57, 0x1b, 0x24, 0x20, 0x12, 0xfb, 0x7a,
        0xe0, 0x7f, 0xa9, 0xba, 0xac, 0x3d, 0xf1, 0x02, 0xe0, 0x08, 0xb0, 0xe2, 0x79,
        0x88, 0x59, 0x88, 0x81, 0xd9, 0x20, 0xa9, 0xe6, 0x4f, 0x56, 0x15, 0xcd
};

static const uint8_t aes_cbc_256_key[] = { 0x60, 0x3d, 0xeb, 0x10, 0x15, 0xca, 0x71, 0xbe,
                                           0x2b, 0x73, 0xae, 0xf0, 0x85, 0x7d, 0x77, 0x81,
                                           0x1f, 0x35, 0x2c, 0x07, 0x3b, 0x61, 0x08, 0xd7,
                                           0x2d, 0x98, 0x10, 0xa3, 0x09, 0x14, 0xdf, 0xf4 };

static uint8_t aes_cbc_256_iv[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
                                    0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f };

static const uint8_t aes_cbc_256_plaintext[] = {
        0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, 0xe9, 0x3d, 0x7e, 0x11, 0x73,
        0x93, 0x17, 0x2a, 0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c, 0x9e, 0xb7,
        0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51, 0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4,
        0x11, 0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef, 0xf6, 0x9f, 0x24, 0x45,
        0xdf, 0x4f, 0x9b, 0x17, 0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10
};

static const uint8_t aes_cbc_256_ciphertext[] = {
        0xf5, 0x8c, 0x4c, 0x04, 0xd6, 0xe5, 0xf1, 0xba, 0x77, 0x9e, 0xab, 0xfb, 0x5f,
        0x7b, 0xfb, 0xd6, 0x9c, 0xfc, 0x4e, 0x96, 0x7e, 0xdb, 0x80, 0x8d, 0x67, 0x9f,
        0x77, 0x7b, 0xc6, 0x70, 0x2c, 0x7d, 0x39, 0xf2, 0x33, 0x69, 0xa9, 0xd9, 0xba,
        0xcf, 0xa5, 0x30, 0xe2, 0x63, 0x04, 0x23, 0x14, 0x61, 0xb2, 0xeb, 0x05, 0xe2,
        0xc3, 0x9b, 0xe9, 0xfc, 0xda, 0x6c, 0x19, 0x07, 0x8c, 0x6a, 0x9d, 0x1b
};

/*
 *  AES-XTS Test vectors from the standard:
 * "IEEE Standard for Cryptographic Protection of Data on Block-Oriented
 * Storage Devices"
 * http://ieeexplore.ieee.org/stamp/stamp.jsp?tp=&arnumber=4493450
 */
static uint8_t aes_xts_128_key1[16] = { 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
                                        0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11 };

static uint8_t aes_xts_128_key2[16] = { 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
                                        0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22 };

static uint8_t aes_xts_128_tweak[16] = { 0x33, 0x33, 0x33, 0x33, 0x33, 0x00, 0x00, 0x00,
                                         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };

static uint8_t aes_xts_128_plaintext[32] = { 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
                                             0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
                                             0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
                                             0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44 };

static uint8_t aes_xts_128_ciphertext[32] = { 0xc4, 0x54, 0x18, 0x5e, 0x6a, 0x16, 0x93, 0x6e,
                                              0x39, 0x33, 0x40, 0x38, 0xac, 0xef, 0x83, 0x8b,
                                              0xfb, 0x18, 0x6f, 0xff, 0x74, 0x80, 0xad, 0xc4,
                                              0x28, 0x93, 0x82, 0xec, 0xd6, 0xd3, 0x94, 0xf0 };

static uint8_t aes_xts_256_key1[32] = { 0x27, 0x18, 0x28, 0x18, 0x28, 0x45, 0x90, 0x45,
                                        0x23, 0x53, 0x60, 0x28, 0x74, 0x71, 0x35, 0x26,
                                        0x62, 0x49, 0x77, 0x57, 0x24, 0x70, 0x93, 0x69,
                                        0x99, 0x59, 0x57, 0x49, 0x66, 0x96, 0x76, 0x27 };

static uint8_t aes_xts_256_key2[32] = { 0x31, 0x41, 0x59, 0x26, 0x53, 0x58, 0x97, 0x93,
                                        0x23, 0x84, 0x62, 0x64, 0x33, 0x83, 0x27, 0x95,
                                        0x02, 0x88, 0x41, 0x97, 0x16, 0x93, 0x99, 0x37,
                                        0x51, 0x05, 0x82, 0x09, 0x74, 0x94, 0x45, 0x92 };

static uint8_t aes_xts_256_tweak[16] = { 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                                         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };

static uint8_t aes_xts_256_plaintext[512] = {
        0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e,
        0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d,
        0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c,
        0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b,
        0x3c, 0x3d, 0x3e, 0x3f, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a,
        0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59,
        0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68,
        0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
        0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86,
        0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95,
        0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0xa0, 0xa1, 0xa2, 0xa3, 0xa4,
        0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0, 0xb1, 0xb2, 0xb3,
        0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, 0xc0, 0xc1, 0xc2,
        0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0, 0xd1,
        0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xe0,
        0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
        0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe,
        0xff, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d,
        0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c,
        0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b,
        0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a,
        0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49,
        0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
        0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
        0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76,
        0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85,
        0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93, 0x94,
        0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0xa0, 0xa1, 0xa2, 0xa3,
        0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0, 0xb1, 0xb2,
        0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, 0xc0, 0xc1,
        0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0,
        0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
        0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee,
        0xef, 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd,
        0xfe, 0xff
};

static uint8_t aes_xts_256_ciphertext[512] = {
        0x1c, 0x3b, 0x3a, 0x10, 0x2f, 0x77, 0x03, 0x86, 0xe4, 0x83, 0x6c, 0x99, 0xe3, 0x70, 0xcf,
        0x9b, 0xea, 0x00, 0x80, 0x3f, 0x5e, 0x48, 0x23, 0x57, 0xa4, 0xae, 0x12, 0xd4, 0x14, 0xa3,
        0xe6, 0x3b, 0x5d, 0x31, 0xe2, 0x76, 0xf8, 0xfe, 0x4a, 0x8d, 0x66, 0xb3, 0x17, 0xf9, 0xac,
        0x68, 0x3f, 0x44, 0x68, 0x0a, 0x86, 0xac, 0x35, 0xad, 0xfc, 0x33, 0x45, 0xbe, 0xfe, 0xcb,
        0x4b, 0xb1, 0x88, 0xfd, 0x57, 0x76, 0x92, 0x6c, 0x49, 0xa3, 0x09, 0x5e, 0xb1, 0x08, 0xfd,
        0x10, 0x98, 0xba, 0xec, 0x70, 0xaa, 0xa6, 0x69, 0x99, 0xa7, 0x2a, 0x82, 0xf2, 0x7d, 0x84,
        0x8b, 0x21, 0xd4, 0xa7, 0x41, 0xb0, 0xc5, 0xcd, 0x4d, 0x5f, 0xff, 0x9d, 0xac, 0x89, 0xae,
        0xba, 0x12, 0x29, 0x61, 0xd0, 0x3a, 0x75, 0x71, 0x23, 0xe9, 0x87, 0x0f, 0x8a, 0xcf, 0x10,
        0x00, 0x02, 0x08, 0x87, 0x89, 0x14, 0x29, 0xca, 0x2a, 0x3e, 0x7a, 0x7d, 0x7d, 0xf7, 0xb1,
        0x03, 0x55, 0x16, 0x5c, 0x8b, 0x9a, 0x6d, 0x0a, 0x7d, 0xe8, 0xb0, 0x62, 0xc4, 0x50, 0x0d,
        0xc4, 0xcd, 0x12, 0x0c, 0x0f, 0x74, 0x18, 0xda, 0xe3, 0xd0, 0xb5, 0x78, 0x1c, 0x34, 0x80,
        0x3f, 0xa7, 0x54, 0x21, 0xc7, 0x90, 0xdf, 0xe1, 0xde, 0x18, 0x34, 0xf2, 0x80, 0xd7, 0x66,
        0x7b, 0x32, 0x7f, 0x6c, 0x8c, 0xd7, 0x55, 0x7e, 0x12, 0xac, 0x3a, 0x0f, 0x93, 0xec, 0x05,
        0xc5, 0x2e, 0x04, 0x93, 0xef, 0x31, 0xa1, 0x2d, 0x3d, 0x92, 0x60, 0xf7, 0x9a, 0x28, 0x9d,
        0x6a, 0x37, 0x9b, 0xc7, 0x0c, 0x50, 0x84, 0x14, 0x73, 0xd1, 0xa8, 0xcc, 0x81, 0xec, 0x58,
        0x3e, 0x96, 0x45, 0xe0, 0x7b, 0x8d, 0x96, 0x70, 0x65, 0x5b, 0xa5, 0xbb, 0xcf, 0xec, 0xc6,
        0xdc, 0x39, 0x66, 0x38, 0x0a, 0xd8, 0xfe, 0xcb, 0x17, 0xb6, 0xba, 0x02, 0x46, 0x9a, 0x02,
        0x0a, 0x84, 0xe1, 0x8e, 0x8f, 0x84, 0x25, 0x20, 0x70, 0xc1, 0x3e, 0x9f, 0x1f, 0x28, 0x9b,
        0xe5, 0x4f, 0xbc, 0x48, 0x14, 0x57, 0x77, 0x8f, 0x61, 0x60, 0x15, 0xe1, 0x32, 0x7a, 0x02,
        0xb1, 0x40, 0xf1, 0x50, 0x5e, 0xb3, 0x09, 0x32, 0x6d, 0x68, 0x37, 0x8f, 0x83, 0x74, 0x59,
        0x5c, 0x84, 0x9d, 0x84, 0xf4, 0xc3, 0x33, 0xec, 0x44, 0x23, 0x88, 0x51, 0x43, 0xcb, 0x47,
        0xbd, 0x71, 0xc5, 0xed, 0xae, 0x9b, 0xe6, 0x9a, 0x2f, 0xfe, 0xce, 0xb1, 0xbe, 0xc9, 0xde,
        0x24, 0x4f, 0xbe, 0x15, 0x99, 0x2b, 0x11, 0xb7, 0x7c, 0x04, 0x0f, 0x12, 0xbd, 0x8f, 0x6a,
        0x97, 0x5a, 0x44, 0xa0, 0xf9, 0x0c, 0x29, 0xa9, 0xab, 0xc3, 0xd4, 0xd8, 0x93, 0x92, 0x72,
        0x84, 0xc5, 0x87, 0x54, 0xcc, 0xe2, 0x94, 0x52, 0x9f, 0x86, 0x14, 0xdc, 0xd2, 0xab, 0xa9,
        0x91, 0x92, 0x5f, 0xed, 0xc4, 0xae, 0x74, 0xff, 0xac, 0x6e, 0x33, 0x3b, 0x93, 0xeb, 0x4a,
        0xff, 0x04, 0x79, 0xda, 0x9a, 0x41, 0x0e, 0x44, 0x50, 0xe0, 0xdd, 0x7a, 0xe4, 0xc6, 0xe2,
        0x91, 0x09, 0x00, 0x57, 0x5d, 0xa4, 0x01, 0xfc, 0x07, 0x05, 0x9f, 0x64, 0x5e, 0x8b, 0x7e,
        0x9b, 0xfd, 0xef, 0x33, 0x94, 0x30, 0x54, 0xff, 0x84, 0x01, 0x14, 0x93, 0xc2, 0x7b, 0x34,
        0x29, 0xea, 0xed, 0xb4, 0xed, 0x53, 0x76, 0x44, 0x1a, 0x77, 0xed, 0x43, 0x85, 0x1a, 0xd7,
        0x7f, 0x16, 0xf5, 0x41, 0xdf, 0xd2, 0x69, 0xd5, 0x0d, 0x6a, 0x5f, 0x14, 0xfb, 0x0a, 0xab,
        0x1c, 0xbb, 0x4c, 0x15, 0x50, 0xbe, 0x97, 0xf7, 0xab, 0x40, 0x66, 0x19, 0x3c, 0x4c, 0xaa,
        0x77, 0x3d, 0xad, 0x38, 0x01, 0x4b, 0xd2, 0x09, 0x2f, 0xa7, 0x55, 0xc8, 0x24, 0xbb, 0x5e,
        0x54, 0xc4, 0xf3, 0x6f, 0xfd, 0xa9, 0xfc, 0xea, 0x70, 0xb9, 0xc6, 0xe6, 0x93, 0xe1, 0x48,
        0xc1, 0x51
};

/* AES-GCM-128 vector, from
 * http://www.ieee802.org/1/files/public/docs2011/bn-randall-test-vectors-0511-v1.pdf */
static const uint8_t aes_gcm_128_key[] = { 0xAD, 0x7A, 0x2B, 0xD0, 0x3E, 0xAC, 0x83, 0x5A,
                                           0x6F, 0x62, 0x0F, 0xDC, 0xB5, 0x06, 0xB3, 0x45 };
static const uint8_t aes_gcm_128_plaintext[] = { 0x08, 0x00, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14,
                                                 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C,
                                                 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24,
                                                 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C,
                                                 0x2D, 0x2E, 0x2F, 0x30, 0x31, 0x32, 0x33, 0x34,
                                                 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x00, 0x02 };
static uint8_t aes_gcm_128_iv[] = { 0x12, 0x15, 0x35, 0x24, 0xC0, 0x89,
                                    0x5E, 0x81, 0xB2, 0xC2, 0x84, 0x65 };
static const uint8_t aes_gcm_128_aad[] = { 0xD6, 0x09, 0xB1, 0xF0, 0x56, 0x63, 0x7A,
                                           0x0D, 0x46, 0xDF, 0x99, 0x8D, 0x88, 0xE5,
                                           0x2E, 0x00, 0xB2, 0xC2, 0x84, 0x65, 0x12,
                                           0x15, 0x35, 0x24, 0xC0, 0x89, 0x5E, 0x81 };
static const uint8_t aes_gcm_128_ciphertext[] = { 0x70, 0x1A, 0xFA, 0x1C, 0xC0, 0x39, 0xC0, 0xD7,
                                                  0x65, 0x12, 0x8A, 0x66, 0x5D, 0xAB, 0x69, 0x24,
                                                  0x38, 0x99, 0xBF, 0x73, 0x18, 0xCC, 0xDC, 0x81,
                                                  0xC9, 0x93, 0x1D, 0xA1, 0x7F, 0xBE, 0x8E, 0xDD,
                                                  0x7D, 0x17, 0xCB, 0x8B, 0x4C, 0x26, 0xFC, 0x81,
                                                  0xE3, 0x28, 0x4F, 0x2B, 0x7F, 0xBA, 0x71, 0x3D };
static uint8_t aes_gcm_128_tag[] = { 0x4F, 0x8D, 0x55, 0xE7, 0xD3, 0xF0, 0x6F, 0xD5,
                                     0xA1, 0x3C, 0x0C, 0x29, 0xB9, 0xD5, 0xB8, 0x80 };

/* AES-GCM-256 vector, from
 * http://csrc.nist.gov/groups/ST/toolkit/BCM/documents/proposedmodes/gcm/gcm-revised-spec.pdf */
static const uint8_t aes_gcm_256_key[] = { 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
                                           0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08,
                                           0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
                                           0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08 };
static const uint8_t aes_gcm_256_plaintext[] = {
        0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5, 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26,
        0x9a, 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda, 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31,
        0x8a, 0x72, 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53, 0x2f, 0xcf, 0x0e, 0x24, 0x49,
        0xa6, 0xb5, 0x25, 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57, 0xba, 0x63, 0x7b, 0x39
};
static const uint8_t aes_gcm_256_aad[] = { 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe,
                                           0xef, 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad,
                                           0xbe, 0xef, 0xab, 0xad, 0xda, 0xd2 };
static uint8_t aes_gcm_256_iv[] = { 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce,
                                    0xdb, 0xad, 0xde, 0xca, 0xf8, 0x88 };
static const uint8_t aes_gcm_256_ciphertext[] = {
        0x52, 0x2d, 0xc1, 0xf0, 0x99, 0x56, 0x7d, 0x07, 0xf4, 0x7f, 0x37, 0xa3, 0x2a, 0x84, 0x42,
        0x7d, 0x64, 0x3a, 0x8c, 0xdc, 0xbf, 0xe5, 0xc0, 0xc9, 0x75, 0x98, 0xa2, 0xbd, 0x25, 0x55,
        0xd1, 0xaa, 0x8c, 0xb0, 0x8e, 0x48, 0x59, 0x0d, 0xbb, 0x3d, 0xa7, 0xb0, 0x8b, 0x10, 0x56,
        0x82, 0x88, 0x38, 0xc5, 0xf6, 0x1e, 0x63, 0x93, 0xba, 0x7a, 0x0a, 0xbc, 0xc9, 0xf6, 0x62
};
static uint8_t aes_gcm_256_tag[] = { 0x76, 0xfc, 0x6e, 0xce, 0x0f, 0x4e, 0x17, 0x68,
                                     0xcd, 0xdf, 0x88, 0x53, 0xbb, 0x2d, 0x55, 0x1b };

#define ADD_CBC_VECTOR(_key, _iv, _plain, _cipher, _descr)                                         \
        { _key, sizeof(_key), _iv, _plain, sizeof(_plain), _cipher, _descr }

static const struct self_test_cbc_vector cbc_vectors[] = {
        ADD_CBC_VECTOR(aes_cbc_128_key, aes_cbc_128_iv, aes_cbc_128_plaintext,
                       aes_cbc_128_ciphertext, "AES128-CBC"),
        ADD_CBC_VECTOR(aes_cbc_192_key, aes_cbc_192_iv, aes_cbc_192_plaintext,
                       aes_cbc_192_ciphertext, "AES192-CBC"),
        ADD_CBC_VECTOR(aes_cbc_256_key, aes_cbc_256_iv, aes_cbc_256_plaintext,
                       aes_cbc_256_ciphertext, "AES256-CBC"),
};

static int
cbc_self_test_vector(const struct self_test_cbc_vector *v)
{
        struct {
                DECLARE_ALIGNED(uint8_t expkey_enc[16 * 15], 16);
                DECLARE_ALIGNED(uint8_t expkey_dec[16 * 15], 16);
        } aes_keys;
        uint8_t scratch[256];

        /* message too long */
        if (v->plaintext_size > sizeof(scratch))
                return 0;

        /* test encrypt direction */
        memset(scratch, 0, sizeof(scratch));
        memcpy(scratch, v->plaintext, v->plaintext_size);

        switch (v->cipher_key_size) {
        case ISAL_CBC_128_BITS:
                _aes_keyexp_128(v->cipher_key, aes_keys.expkey_enc, aes_keys.expkey_dec);
                _aes_cbc_enc_128(scratch, v->cipher_iv, aes_keys.expkey_enc, scratch,
                                 v->plaintext_size);
                break;
        case ISAL_CBC_192_BITS:
                _aes_keyexp_192(v->cipher_key, aes_keys.expkey_enc, aes_keys.expkey_dec);
                _aes_cbc_enc_192(scratch, v->cipher_iv, aes_keys.expkey_enc, scratch,
                                 v->plaintext_size);
                break;
        case ISAL_CBC_256_BITS:
                _aes_keyexp_256(v->cipher_key, aes_keys.expkey_enc, aes_keys.expkey_dec);
                _aes_cbc_enc_256(scratch, v->cipher_iv, aes_keys.expkey_enc, scratch,
                                 v->plaintext_size);
                break;
        default:
                /* invalid key size */
                return 0;
        }

        /* check for cipher text mismatch */
        if (memcmp(scratch, v->ciphertext, v->plaintext_size))
                return 0;

        /* test decrypt direction */
        memset(scratch, 0, sizeof(scratch));
        memcpy(scratch, v->ciphertext, v->plaintext_size);

        switch (v->cipher_key_size) {
        case ISAL_CBC_128_BITS:
                _aes_cbc_dec_128(scratch, v->cipher_iv, aes_keys.expkey_dec, scratch,
                                 v->plaintext_size);
                break;
        case ISAL_CBC_192_BITS:
                _aes_cbc_dec_192(scratch, v->cipher_iv, aes_keys.expkey_dec, scratch,
                                 v->plaintext_size);
                break;
        case ISAL_CBC_256_BITS:
                _aes_cbc_dec_256(scratch, v->cipher_iv, aes_keys.expkey_dec, scratch,
                                 v->plaintext_size);
                break;
        default:
                /* invalid key size */
                return 0;
        }

        /* check for plain text mismatch */
        if (memcmp(scratch, v->plaintext, v->plaintext_size))
                return 0;

        return 1;
}

static int
_aes_cbc_self_test(void)
{
        for (uint32_t i = 0; i < DIM(cbc_vectors); i++) {
                const struct self_test_cbc_vector *v = &cbc_vectors[i];

                if (cbc_self_test_vector(v) == 0)
                        return 1;
        }

        return 0;
}

#define ADD_XTS_VECTOR(_key1, _key2, _tweak, _plain, _cipher, _descr)                              \
        { _key1, _key2, sizeof(_key1), _tweak, _plain, sizeof(_plain), _cipher, _descr }

static const struct self_test_xts_vector xts_vectors[] = {
        ADD_XTS_VECTOR(aes_xts_128_key1, aes_xts_128_key2, aes_xts_128_tweak, aes_xts_128_plaintext,
                       aes_xts_128_ciphertext, "AES128-XTS"),
        ADD_XTS_VECTOR(aes_xts_256_key1, aes_xts_256_key2, aes_xts_256_tweak, aes_xts_256_plaintext,
                       aes_xts_256_ciphertext, "AES256-XTS"),
};

static int
xts_self_test_vector(const struct self_test_xts_vector *v)
{
        struct {
                DECLARE_ALIGNED(uint8_t expkey1_enc[16 * 15], 16);
                DECLARE_ALIGNED(uint8_t expkey1_dec[16 * 15], 16);
                DECLARE_ALIGNED(uint8_t expkey2_enc[16 * 15], 16);
                DECLARE_ALIGNED(uint8_t expkey2_dec[16 * 15], 16);
        } aes_keys;
        uint8_t scratch[512];

        /* message too long */
        if (v->plaintext_size > sizeof(scratch))
                return 0;

        /* test encrypt direction */
        memset(scratch, 0, sizeof(scratch));
        memcpy(scratch, v->plaintext, v->plaintext_size);

        switch (v->cipher_key_size) {
        case 16:
                _XTS_AES_128_enc(v->cipher_key2, v->cipher_key1, v->tweak, v->plaintext_size,
                                 scratch, scratch);
                break;
        case 32:
                _XTS_AES_256_enc(v->cipher_key2, v->cipher_key1, v->tweak, v->plaintext_size,
                                 scratch, scratch);
                break;
        default:
                /* invalid key size */
                return 0;
        }

        /* check for ciphertext mismatch */
        if (memcmp(scratch, v->ciphertext, v->plaintext_size))
                return 0;

        /* test encrypt direction (expanded keys) */
        memset(scratch, 0, sizeof(scratch));
        memcpy(scratch, v->plaintext, v->plaintext_size);
        switch (v->cipher_key_size) {
        case 16:
                _aes_keyexp_128(v->cipher_key1, aes_keys.expkey1_enc, aes_keys.expkey1_dec);
                _aes_keyexp_128(v->cipher_key2, aes_keys.expkey2_enc, aes_keys.expkey2_dec);
                _XTS_AES_128_enc_expanded_key(aes_keys.expkey2_enc, aes_keys.expkey1_enc, v->tweak,
                                              v->plaintext_size, scratch, scratch);
                break;
        case 32:
                _aes_keyexp_256(v->cipher_key1, aes_keys.expkey1_enc, aes_keys.expkey1_dec);
                _aes_keyexp_256(v->cipher_key2, aes_keys.expkey2_enc, aes_keys.expkey2_dec);
                _XTS_AES_256_enc_expanded_key(aes_keys.expkey2_enc, aes_keys.expkey1_enc, v->tweak,
                                              v->plaintext_size, scratch, scratch);
                break;
        default:
                /* invalid key size */
                return 0;
        }

        /* check for ciphertext mismatch */
        if (memcmp(scratch, v->ciphertext, v->plaintext_size))
                return 0;

        /* test decrypt direction */
        memset(scratch, 0, sizeof(scratch));
        memcpy(scratch, v->ciphertext, v->plaintext_size);

        switch (v->cipher_key_size) {
        case 16:
                _XTS_AES_128_dec(v->cipher_key2, v->cipher_key1, v->tweak, v->plaintext_size,
                                 scratch, scratch);
                break;
        case 32:
                _XTS_AES_256_dec(v->cipher_key2, v->cipher_key1, v->tweak, v->plaintext_size,
                                 scratch, scratch);
                break;
        default:
                /* invalid key size */
                return 0;
        }

        /* check for plaintext mismatch */
        if (memcmp(scratch, v->plaintext, v->plaintext_size))
                return 0;

        /* test decrypt direction (expanded keys) */
        memset(scratch, 0, sizeof(scratch));
        memcpy(scratch, v->ciphertext, v->plaintext_size);
        switch (v->cipher_key_size) {
        case 16:
                _aes_keyexp_128(v->cipher_key1, aes_keys.expkey1_enc, aes_keys.expkey1_dec);
                _aes_keyexp_128(v->cipher_key2, aes_keys.expkey2_enc, aes_keys.expkey2_dec);
                _XTS_AES_128_dec_expanded_key(aes_keys.expkey2_enc, aes_keys.expkey1_dec, v->tweak,
                                              v->plaintext_size, scratch, scratch);
                break;
        case 32:
                _aes_keyexp_256(v->cipher_key1, aes_keys.expkey1_enc, aes_keys.expkey1_dec);
                _aes_keyexp_256(v->cipher_key2, aes_keys.expkey2_enc, aes_keys.expkey2_dec);
                _XTS_AES_256_dec_expanded_key(aes_keys.expkey2_enc, aes_keys.expkey1_dec, v->tweak,
                                              v->plaintext_size, scratch, scratch);
                break;
        default:
                /* invalid key size */
                return 0;
        }

        /* check for plaintext mismatch */
        if (memcmp(scratch, v->plaintext, v->plaintext_size))
                return 0;

        return 1;
}

static int
_aes_xts_self_test(void)
{
        for (uint32_t i = 0; i < DIM(xts_vectors); i++) {
                const struct self_test_xts_vector *v = &xts_vectors[i];

                if (xts_self_test_vector(v) == 0)
                        return 1;
        }

        return 0;
}

#define ADD_GCM_VECTOR(_key, _iv, _plain, _cipher, _aad, _tag, _descr)                             \
        { _key, sizeof(_key), _iv,  _plain,       sizeof(_plain), _cipher,                         \
          _aad, sizeof(_aad), _tag, sizeof(_tag), _descr }

static const struct self_test_gcm_vector gcm_vectors[] = {
        ADD_GCM_VECTOR(aes_gcm_128_key, aes_gcm_128_iv, aes_gcm_128_plaintext,
                       aes_gcm_128_ciphertext, aes_gcm_128_aad, aes_gcm_128_tag, "AES128-GCM"),
        ADD_GCM_VECTOR(aes_gcm_256_key, aes_gcm_256_iv, aes_gcm_256_plaintext,
                       aes_gcm_256_ciphertext, aes_gcm_256_aad, aes_gcm_256_tag, "AES256-GCM"),
};

static int
gcm_self_test_vector(const struct self_test_gcm_vector *v)
{
        struct isal_gcm_key_data gkey;
        struct isal_gcm_context_data gctx;
        uint8_t scratch[512];
        uint8_t result_tag[16];

        /* message too long */
        if (v->plaintext_size > sizeof(scratch))
                return 0;

        /* Precompute AES and GHASH keys */
        switch (v->cipher_key_size) {
        case 16:
                _aes_gcm_pre_128(v->key, &gkey);
                break;
        case 32:
                _aes_gcm_pre_256(v->key, &gkey);
                break;
        default:
                /* invalid key size */
                return 0;
        }

        /* test encrypt direction (single call API) */
        memset(scratch, 0, sizeof(scratch));
        memcpy(scratch, v->plaintext, v->plaintext_size);
        switch (v->cipher_key_size) {
        case 16:
                _aes_gcm_enc_128(&gkey, &gctx, scratch, scratch, v->plaintext_size, v->cipher_iv,
                                 v->aad, v->aad_size, result_tag, v->tag_size);
                break;
        case 32:
                _aes_gcm_enc_256(&gkey, &gctx, scratch, scratch, v->plaintext_size, v->cipher_iv,
                                 v->aad, v->aad_size, result_tag, v->tag_size);
                break;
        default:
                /* invalid key size */
                return 0;
        }

        /* check for ciphertext mismatch */
        if (memcmp(scratch, v->ciphertext, v->plaintext_size))
                return 0;

        /* check for authentication tag mismatch */
        if (memcmp(result_tag, v->tag, v->tag_size))
                return 0;

        /* test encrypt direction (multi-call API) */
        memset(scratch, 0, sizeof(scratch));
        memcpy(scratch, v->plaintext, v->plaintext_size);
        switch (v->cipher_key_size) {
        case 16:
                _aes_gcm_init_128(&gkey, &gctx, v->cipher_iv, v->aad, v->aad_size);
                _aes_gcm_enc_128_update(&gkey, &gctx, scratch, scratch, v->plaintext_size);
                _aes_gcm_enc_128_finalize(&gkey, &gctx, v->tag, v->tag_size);
                break;
        case 32:
                _aes_gcm_init_256(&gkey, &gctx, v->cipher_iv, v->aad, v->aad_size);
                _aes_gcm_enc_256_update(&gkey, &gctx, scratch, scratch, v->plaintext_size);
                _aes_gcm_enc_256_finalize(&gkey, &gctx, v->tag, v->tag_size);
                break;
        default:
                /* invalid key size */
                return 0;
        }

        /* check for ciphertext mismatch */
        if (memcmp(scratch, v->ciphertext, v->plaintext_size))
                return 0;

        /* check for authentication tag mismatch */
        if (memcmp(result_tag, v->tag, v->tag_size))
                return 0;

        /* test decrypt direction (single-call API) */
        memset(scratch, 0, sizeof(scratch));
        memcpy(scratch, v->ciphertext, v->plaintext_size);

        switch (v->cipher_key_size) {
        case 16:
                _aes_gcm_dec_128(&gkey, &gctx, scratch, scratch, v->plaintext_size, v->cipher_iv,
                                 v->aad, v->aad_size, result_tag, v->tag_size);
                break;
        case 32:
                _aes_gcm_dec_256(&gkey, &gctx, scratch, scratch, v->plaintext_size, v->cipher_iv,
                                 v->aad, v->aad_size, result_tag, v->tag_size);
                break;
        default:
                /* invalid key size */
                return 0;
        }

        /* check for plaintext mismatch */
        if (memcmp(scratch, v->plaintext, v->plaintext_size))
                return 0;

        /* check for authentication tag mismatch */
        if (memcmp(result_tag, v->tag, v->tag_size))
                return 0;

        /* test decrypt direction (multi-call API) */
        memset(scratch, 0, sizeof(scratch));
        memcpy(scratch, v->ciphertext, v->plaintext_size);
        switch (v->cipher_key_size) {
        case 16:
                _aes_gcm_init_128(&gkey, &gctx, v->cipher_iv, v->aad, v->aad_size);
                _aes_gcm_dec_128_update(&gkey, &gctx, scratch, scratch, v->plaintext_size);
                _aes_gcm_dec_128_finalize(&gkey, &gctx, v->tag, v->tag_size);
                break;
        case 32:
                _aes_gcm_init_256(&gkey, &gctx, v->cipher_iv, v->aad, v->aad_size);
                _aes_gcm_dec_256_update(&gkey, &gctx, scratch, scratch, v->plaintext_size);
                _aes_gcm_dec_256_finalize(&gkey, &gctx, v->tag, v->tag_size);
                break;
        default:
                /* invalid key size */
                return 0;
        }

        /* check for plaintext mismatch */
        if (memcmp(scratch, v->plaintext, v->plaintext_size))
                return 0;

        /* check for authentication tag mismatch */
        if (memcmp(result_tag, v->tag, v->tag_size))
                return 0;

        return 1;
}

static int
_aes_gcm_self_test(void)
{
        for (unsigned i = 0; i < DIM(gcm_vectors); i++) {
                const struct self_test_gcm_vector *v = &gcm_vectors[i];

                if (gcm_self_test_vector(v) == 0)
                        return 1;
        }

        return 0;
}

int
_aes_self_tests(void)
{
        int ret;

        ret = _aes_cbc_self_test();
        ret |= _aes_xts_self_test();
        ret |= _aes_gcm_self_test();

        return ret;
}
